import { Box, FieldEffect, useFieldName, useModal, useSaveFormQuery, useSimpleMemo } from '@/components';
import { nextTick } from '@/utils';
import { catchAndScrollFor } from '@/utils/fp';
import { Button, Col, Form, Input, Select, Space } from 'antd';
import clsx from 'clsx';
import * as PropTypes from 'prop-types';
import React, { useDebugValue, useEffect, useMemo, useState } from 'react';
import FieldCols from './FieldCols';
import styles from './index.less';
import { defaultCol } from './shared';

const AutoFuzzyFiled = ({ value, onChange, ...rest }) => {
  const [name] = useFieldName().slice(-1);
  const options = useMemo(
    () => [
      { value: 'searchFuzzy', label: '模糊' },
      { value: 't', label: '精确' },
    ],
    [],
  );
  const [type, setType] = useState('searchFuzzy');
  const fieldName = type === 'searchFuzzy' ? name : name.replace(/_[a-z]/g, (t) => t.substr(1).toUpperCase());
  const effectName = useSimpleMemo([type, fieldName]);

  useDebugValue(effectName);

  return (
    <>
      <FieldEffect preserve={false} name={effectName} initialValue={value || null} value={value || null} />
      <Box component={Input.Group} flex compact>
        <Select showArrow={false} value={type} options={options} onChange={setType} />
        <Box component={Input} grow {...rest} value={value} onChange={onChange} />
      </Box>
    </>
  );
};

const useAutoFuzzyFields = (fields) => {
  return useSimpleMemo(
    fields?.map((item) => {
      if (Array.isArray(item.name) && item.name[0] === 'auto') {
        item.type = AutoFuzzyFiled;
      }
      return item;
    }) ?? [],
  );
};

function SearchFields(props) {
  const modal = useModal();
  let {
    className,
    style,
    onSubmit,
    submitText,
    onReset,
    resetText,
    onError,
    form,
    fields,
    saveQuery = !modal.isModal,
    lazy = false,
    ...rest
  } = props;
  const [thisForm] = Form.useForm(form);
  const updateQuery = useSaveFormQuery(saveQuery, thisForm);

  const colProps = useSimpleMemo(props.colProps ?? defaultCol);

  const handleSubmit = async () => {
    try {
      let { auto, ...values } = await thisForm.validateFields().catch(catchAndScrollFor(form));
      updateQuery();
      if (typeof onSubmit === 'function') onSubmit(values);
    } catch (e) {
      if (typeof onError === 'function') onError(e);
    }
  };

  const handleReset = () => {
    thisForm.resetFields();
    updateQuery();
    if (typeof onReset === 'function') onReset(thisForm.getFieldsValue());
  };

  useEffect(() => {
    if (!lazy) nextTick(handleSubmit);
  }, []);

  const autoFields = useAutoFuzzyFields(fields);

  return (
    <Form form={thisForm} className={clsx(styles.searchBox, className)} style={style} onFinish={handleSubmit}>
      <FieldCols form={thisForm} fields={autoFields} {...rest}>
        <Col {...colProps} className={clsx(styles.searchCol, colProps?.className)}>
          <Space size='middle'>
            <Button onClick={handleReset}>{resetText}</Button>
            <Button type='primary' onClick={handleSubmit}>
              {submitText}
            </Button>
          </Space>
        </Col>
      </FieldCols>
      <button type='submit' style={{ display: 'none' }} />
    </Form>
  );
}

SearchFields.propTypes = {
  className: PropTypes.any,

  style: PropTypes.object,

  /** 回车或点击查询回调 */
  onSubmit: PropTypes.func,

  /** 查询按钮文字 */
  submitText: PropTypes.string,

  /** 重置回调 */
  onReset: PropTypes.func,

  /** 重置按钮文字 */
  resetText: PropTypes.string,

  /** 校验失败回调 */
  onError: PropTypes.func,

  /** 表单保存到url中 */
  saveQuery: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),

  ...FieldCols.propTypes,
};

SearchFields.defaultProps = { submitText: '查询', resetText: '重置' };

export default SearchFields;
